package com.netflexitysolutions.amazonws.sdb.orm.filter;

import com.netflexitysolutions.amazonws.sdb.orm.metadata.SimpleDBMapping;

/**
 * Utility class that contains factory convenient methods for predicate objects.
 * 
 * @see com.netflexitysolutions.amazonws.sdb.orm.filter.Filter
 * @author netflexity
 *
 */
public final class Predicates {
	
	/**
	 * @param <T>
	 * @param type
	 * @param mapping
	 * @param fieldName
	 * @param comparisonValues
	 * @return
	 */
	public static <T> Predicate<T> getInPredicate(Class<T> type, SimpleDBMapping mapping, String fieldName, Object comparisonValues[]) {
        return new SimplePredicate<T>(ComparisonType.IN, type, mapping, fieldName, comparisonValues);
    }
	
	/**
	 * @param <T>
	 * @param type
	 * @param mapping
	 * @param fieldName
	 * @param comparisonValues
	 * @return
	 */
	public static <T> Predicate<T> getNotInPredicate(Class<T> type, SimpleDBMapping mapping, String fieldName, Object comparisonValues[]) {
        return new SimplePredicate<T>(ComparisonType.NOT_IN, type, mapping, fieldName, comparisonValues);
    }
	
    /**
    * This is equivalent to <CODE>getEqualityPredicate(recType, fieldName, comparisonValue, false)</CODE>
     */
    public static <T> Predicate<T> getEqualityPredicate(Class<T> type, SimpleDBMapping mapping, String fieldName, String comparisonValue) {
        return getEqualityPredicate(type, mapping, fieldName, comparisonValue, false);
    }

    /**
     * @param type The type of record we are interested in.
     * @param fieldName The name of the field of the record we are filtering on.
     * @param comparisonValue The value to compare that field's value with.
    *  @param caseInsensitive whether to perform a case-insensitive match
     * @return A predicate that represents all records of a given type whose given field 
     * has the given a value.
    * <BR>If caseInsensitive is true, the comparisonValue must be a string (of course!)
     */
    public static <T> Predicate<T> getEqualityPredicate(Class<T> type, SimpleDBMapping mapping, String fieldName, String comparisonValue, boolean caseInsensitive) {
        return new SimplePredicate<T>(ComparisonType.EQUALS, type, mapping, fieldName, comparisonValue, caseInsensitive);
    }

    /**
     * @param type The type of record we are interested in.
     * @param fieldName The name of the field of the record we are filtering on.
     * @param comparisonValue The value to compare that field's value with.
     * @param caseInsensitive whether to do a case-insensitive match.
     * @return A predicate that represents all records of a given type whose given field 
     * is <EM>not</EM> of the given value.
     * <BR>If caseInsensitive is true, the comparisonValue must be a string (of course!)
     */
    public static <T> Predicate<T> getInequalityPredicate(Class<T> type, SimpleDBMapping mapping, String fieldName, String comparisonValue, boolean caseInsensitive) {
        return new SimplePredicate<T>(ComparisonType.NOT_EQUALS, type, mapping, fieldName, comparisonValue, caseInsensitive);
    }

    /**
    * this is equivalent to <CODE>getInequalityPredicate(type, fieldName, comparisonValue, false)</CODE>
     */
    public static <T> Predicate<T> getInequalityPredicate(Class<T> type, SimpleDBMapping mapping, String fieldName, String comparisonValue) {
        return getInequalityPredicate(type, mapping, fieldName, comparisonValue, false);
    }

    /**
     * @param type The type of record we are interested in.
     * @param fieldName The name of the field of the record we are filtering on.
     * @param comparisonValue The value to compare that field's value with.
     * @param comparator A custom comparator to use for comparisons
     * @return A predicate that represents all records of a given type whose given field 
     * is <EM>less than</EM> the given value.
     */
    public static <T> Predicate<T> getLessThanPredicate(Class<T> type, SimpleDBMapping mapping, String fieldName, String comparisonValue) {
        return new SimplePredicate<T>(ComparisonType.LESS_THAN, type, mapping, fieldName, comparisonValue);
    }

    /**
     * @param type The type of record we are interested in.
     * @param fieldName The name of the field of the record we are filtering on.
     * @param comparisonValue The value to compare that field's value with.
     * @return A predicate that represents all records of a given type whose given field 
     * is <EM>greater than</EM> the given value.
     */
    public static <T> Predicate<T> getGreaterThanPredicate(Class<T> type, SimpleDBMapping mapping, String fieldName, String comparisonValue) {
        return new SimplePredicate<T>(ComparisonType.GREATER_THAN, type, mapping, fieldName, comparisonValue);
    }
    
    /**
     * @param type The type of record we are interested in.
     * @param fieldName The name of the field of the record we are filtering on.
     * @param comparisonValue The value to compare that field's value with.
     * @return A predicate that represents all records of a given type whose given field 
     * is <EM>less than or equal to</EM> the given value.
     */
    public static <T> Predicate<T> getLessThanEqualsPredicate(Class<T> type, SimpleDBMapping mapping, String fieldName, String comparisonValue) {
        return new SimplePredicate<T>(ComparisonType.LESS_THAN_EQUALS, type, mapping, fieldName, comparisonValue);
    }

    /**
     * @param type The type of record we are interested in.
     * @param fieldName The name of the field of the record we are filtering on.
     * @param comparisonValue The value to compare that field's value with.
     * @return A predicate that represents all records of a given type whose given field 
     * is <EM>greater than or equal to</EM> the given value.
     */
    public static <T> Predicate<T> getGreaterThanEqualsPredicate(Class<T> type, SimpleDBMapping mapping, String fieldName, String comparisonValue) {
    	return new SimplePredicate<T>(ComparisonType.GREATER_THAN_EQUALS, type, mapping, fieldName, comparisonValue);
    }

    /**
     * @param type The type of record we are interested in.
     * @param fieldName The name of the field of the record we are filtering on.
     * @param comparisonValue The string to compare with
     * @param caseInsensitive whether to do a case-insensitive match.
     * @return A predicate that represents all records of a given type whose given field 
     * is <EM>greater than or equal to</EM> the given value.
     */
    public static <T> Predicate<T> getLikePredicate(Class<T> type, SimpleDBMapping mapping, String fieldName, String comparisonValue, boolean caseInsensitive) {
        return new SimplePredicate<T>(ComparisonType.LIKE, type, mapping, fieldName, comparisonValue, caseInsensitive);
    }

    /**
     * @param type The type of record we are interested in.
     * @param fieldName The name of the field of the record we are filtering on.
     * @param comparisonValue The string to compare with
     * @param caseInsensitive whether to do a case-insensitive match.
    * @return A predicate that represents all records of a given type whose given field 
     * is <EM>greater than or equal to</EM> the given value.
     */
    public static <T> Predicate<T> getNotLikePredicate(Class<T> type, SimpleDBMapping mapping, String fieldName, String comparisonValue, boolean caseInsensitive) {
        return new SimplePredicate<T>(ComparisonType.NOT_LIKE, type, mapping, fieldName, comparisonValue, caseInsensitive);
    }

    /**
     * @param lhs left-hand side
     * @param  rhs right-hand side
     * @return A predicate that represents the intersection of the two conditions. A logical AND
     */
    public static <T> Predicate<T> getIntersection(Predicate<T> lhs, Predicate<T> rhs) {
        return new CompoundPredicate<T>(CompoundPredicate.INTERSECTION, lhs, rhs);
    }

    /**
     * @param lhs left-hand side
     * @param  rhs right-hand side
     * @return A predicate that represents the union of the two conditions. A logical OR
     */
    public static <T> Predicate<T> getUnion(Predicate<T> lhs, Predicate<T> rhs) {
        return new CompoundPredicate<T>(CompoundPredicate.UNION, lhs, rhs);
    }
}
